using System.Collections.Generic;
using System.Security;
using System.Xml.Serialization;

namespace NSecurity.Providers
{
    public class AccessControlMemoryProvider<TSecurable, TVerb, TSubject> : AccessControlProviderBase<TSecurable, TVerb, TSubject>
        where TSecurable : class
        where TVerb : class
        where TSubject : class
    {
        private readonly object Lock = new object();

        protected volatile List<AccessControlEntry> Entries;

        protected override AccessControlEntry AddAccessControlEntry(TSecurable securable, TVerb verb, TSubject subject, AccessType accessType)
        {
            var entry = AccessControlEntry.Create(securable, verb, subject, accessType);
            this.Entries.Add(entry);
            return entry;
        }

        protected override void ClearAccessControlEntries()
        {
            this.Entries.Clear();
        }

        protected override IEnumerable<AccessControlEntry> FindAllAccessControlEntries(TSecurable securable, TVerb verb, IEnumerable<TSubject> subjects)
        {
            var result = new List<AccessControlEntry>();
            foreach (var subject in subjects)
            {
                var all = this.Entries.FindAll(e => e.Securable.Equals(securable) && e.Verb.Equals(verb) && e.Subject.Equals(subject));
                result.AddRange(all);
            }

            return result;
        }

        protected override void InitializeAccessControlEntries()
        {
            if (this.Entries == null)
            {
                lock (this.Lock)
                {
                    if (this.Entries == null)
                    {
                        this.Entries = new List<AccessControlEntry>();
                    }
                }
            }

            if (this.Entries == null)
            {
                throw new SecurityException("Unable to initialize access control entry list.");
            }
        }

        public override void PersistChanges()
        {
        }

        public override void LoadAccessControl(string entries = null)
        {
        }
    }
}